今天繼續來完成前端網站 React 的部分,首先有好幾個地方要修正,像是資料呈現的屬性資料顯然是不夠的、圖表上的顯然是庫存而不是價格、每週的銷售紀錄等等呈現。
// types.tsx
export type SaleRecord = {
week: number;
price: number; // 價錢
initialStock: number; // 存貨,初始的存貨量
sales: number; // 銷售,賣出的數量
remainingStock: number; // 剩餘存貨 = 初始存貨 - 賣出的數量
revenue: number; // 營收 = 價錢 x 賣出的數量
accumulatedRevenue: number; // 累積營收
};
修正需要呈現的資料屬性。
// components/LineChart.tsx
import React from 'react';
import { Line } from 'react-chartjs-2';
import { SaleRecord } from './types';
import { Chart, registerables } from 'chart.js';
type Props = {
data: SaleRecord[];
};
const LineChart: React.FC<Props> = ({ data }) => {
Chart.register(...registerables);
const chartData = {
labels: data.map(record => `Week ${record.week}`),
datasets: [
{
label: 'Remaining Stock',
data: data.map(record => record.remainingStock),
fill: false,
backgroundColor: 'rgb(75, 192, 192)',
borderColor: 'rgba(75, 192, 192, 0.2)',
},
],
};
return <Line data={chartData} />;
};
export default LineChart;
大致上修改一下呈現的是剩餘存貨量~
// components/PricingControl.tsx
import React, { useState } from 'react';
type Props = {
onSelect: (price: number) => void;
};
const PricingControl: React.FC<Props> = ({ onSelect }) => {
const [selectedPrice, setSelectedPrice] = useState<number | null>(null);
const prices = [60, 54, 48, 36];
return (
<div>
{prices.map((price) => (
<button
key={price}
onClick={() => {
setSelectedPrice(price);
onSelect(price);
}}
disabled={selectedPrice !== null && price > selectedPrice}
>
${price}
</button>
))}
</div>
);
};
export default PricingControl;
大概修正一下銷售數字和銷售一但低價賣出,就不能回到高價賣出了。
// logic/salesLogic.ts
export const simulateSales = (remainingStock: number): number => {
const sales = Math.floor(Math.random() * (120 - 70 + 1) + 70);
return Math.min(sales, remainingStock);
}
修正一下銷售的隨機,讓他先介於70~120之間,並且不能超過剩餘存貨數量。
// components/SalesTable.tsx
import React from 'react';
import { SaleRecord } from './types';
type Props = {
data: SaleRecord[];
};
const SalesTable: React.FC<Props> = ({ data }) => {
return (
<table>
<thead>
<tr>
<th>週</th>
<th>價格</th>
<th>存貨</th>
<th>銷售</th>
<th>剩餘存貨</th>
<th>營收</th>
<th>累計營收</th>
</tr>
</thead>
<tbody>
{data.map(record => (
<tr key={record.week}>
<td>{record.week}</td>
<td>{record.price}</td>
<td>{record.initialStock}</td>
<td>{record.sales}</td>
<td>{record.remainingStock}</td>
<td>{record.revenue}</td>
<td>{record.accumulatedRevenue}</td>
</tr>
))}
</tbody>
</table>
);
};
export default SalesTable;
先製作一個簡單的表格呈現,之後再美化。
// App.tsx
import React, { useState } from 'react';
import LineChart from './Component/LineChart';
import PricingControl from './Component/PricingControl';
import { SaleRecord } from './Component/types';
import { simulateSales } from './Component/salesLogic';
import SalesTable from './Component/SalesTable';
const INITIAL_STOCK = 2000;
const App: React.FC = () => {
const [salesData, setSalesData] = useState<SaleRecord[]>([
{ week: 1, price: 60, initialStock: INITIAL_STOCK, sales: 0, remainingStock: INITIAL_STOCK, revenue: 0, accumulatedRevenue: 0 },
]);
const handlePricingSelect = (price: number) => {
const currentWeek = salesData.length;
const previousRecord = salesData[currentWeek - 1];
const sales = simulateSales(previousRecord.remainingStock);
const newRemainingStock = previousRecord.remainingStock - sales;
const revenue = sales * price;
const accumulatedRevenue = previousRecord.accumulatedRevenue + revenue;
const record: SaleRecord = {
week: currentWeek + 1,
price,
initialStock: INITIAL_STOCK,
sales,
remainingStock: newRemainingStock,
revenue,
accumulatedRevenue,
};
setSalesData([...salesData, record]);
};
return (
<div className="App">
<h1>Retail Simulation</h1>
<PricingControl onSelect={handlePricingSelect} />
<LineChart data={salesData} />
<SalesTable data={salesData} />
</div>
);
};
export default App;
其中針對 handlePricingSelect
做了點修正,並且新增 <SalesTable data={salesData} />
的呈現。
今天就先到這裡好了,明天在繼續優化一下。